package com.cambright.stack.components
{
	import com.cambright.Enumerator;
	import com.cambright.stack.components.layout.Alignment;
	import com.cambright.stack.components.layout.Direction;
	import com.cambright.stack.components.layout.Element;
	import com.cambright.stack.components.layout.Fill;
	
	public class AlignmentLayoutComponent extends LayoutComponent
	{
		private var _gapChanged:Boolean = true;
		private var _directionChanged:Boolean = true;
		private var _alignmentChanged:Boolean = true;
		
		private var _directionField1:String;
		private var _directionField2:String;
		private var _sizeField1:String;
		private var _sizeField2:String;
		private var _pointField1:String;
		private var _pointField2:String;
		private var _marginField1:String;
		private var _marginField2:String;
		private var _marginField3:String;
		private var _marginField4:String;	
		private var _alignmentKey1:String;
		private var _alignmentKey2:String;
		private var _alignmentKey3:String;
		private var _alignmentKey4:String;	
		
		override protected function invoke():void
		{
			super.invoke();
			
			_directionField1 = "HORIZONTAL";
			_directionField2 = "VERTICAL";
			_sizeField1 = "width";
			_sizeField2 = "height";
			_pointField1 = "x";
			_pointField2 = "y";
			_marginField1 = "left";
			_marginField2 = "right";
			_marginField3 = "top";
			_marginField4 = "bottom";
			
			_alignmentKey1 = "CENTER";
			_alignmentKey2 = "RIGHT";
			_alignmentKey3 = "TOP";
			_alignmentKey4 = "BOTTOM";
		}
		
		override protected function dispose():void
		{
			_alignment = null;
			_direction = null;
			super.dispose();
		}
		
		private var _gap:int = 0;
		public function get gap():int
		{
			return _gap;
		}
		public function set gap(value:int):void
		{
			if(value == _gap) return;
			
			_gap = value;
			_gapChanged = true;
		}
		
		private var _direction:Direction = Direction.HORIZONTAL;
		public function get direction():Direction
		{
			return _direction;
		}
		public function set direction(value:Direction):void
		{
			if(value == _direction) return;
			_direction = value;
			
			if(value == Direction.HORIZONTAL)
			{
				_directionField1 = "HORIZONTAL";
				_directionField2 = "VERTICAL";
				_sizeField1 = "width";
				_sizeField2 = "height";
				_pointField1 = "x";
				_pointField2 = "y";
				_marginField1 = "left";
				_marginField2 = "right";
				_marginField3 = "top";
				_marginField4 = "bottom";
				
				_alignmentKey1 = "CENTER";
				_alignmentKey2 = "RIGHT";
				_alignmentKey3 = "TOP";
				_alignmentKey4 = "BOTTOM";
			}
			else if(value == Direction.VERTICAL)
			{
				_directionField2 = "HORIZONTAL";
				_directionField1 = "VERTICAL";
				_sizeField2 = "width";
				_sizeField1 = "height";
				_pointField2 = "x";
				_pointField1 = "y";
				_marginField3 = "left";
				_marginField4 = "right";
				_marginField1 = "top";
				_marginField2 = "bottom";
				
				_alignmentKey1 = "MIDDLE";
				_alignmentKey2 = "BOTTOM";
				_alignmentKey3 = "LEFT";
				_alignmentKey4 = "RIGHT";
			}
			
			_directionChanged = true;
		}
		
		private var _alignment:Alignment = Alignment.MIDDLE_CENTER;
		public function get alignment():Alignment
		{
			return _alignment;
		}
		public function set alignment(value:Alignment):void
		{
			if(value == _alignment) return;
			_alignment = value;
			_alignmentChanged = true;
		}
		
		override protected function get isChanged():Boolean
		{
			var isChanged:Boolean = super.isChanged;
			isChanged = _gapChanged || isChanged;
			isChanged = _directionChanged || isChanged;
			isChanged = _alignmentChanged || isChanged;
			return isChanged;
		}
		
		override protected function flush():void
		{
			super.flush();
			
			_gapChanged = false;
			_directionChanged = false;
			_alignmentChanged = false;
			
			var fillCount:int = 0;
			var unfillSize:int = 0;
			
			var enumerator:Enumerator = elementEnumerator;
			var element:Element;
			while(enumerator.next())
			{
				element = enumerator.current;
				if((element.fill.value & (Fill[_directionField1] as Fill).value) > 0)
					++ fillCount;
				else unfillSize += element.display[_sizeField1];
			}
			
			var gapSize:int = 0;
			if(elementCount > 1) 
				gapSize += (elementCount - 1) * _gap;
			
			var size1:int = this[_sizeField1];
			var size2:int = this[_sizeField2];
			
			var start:int = margin[_marginField1];
			var end:int = size1 - margin[_marginField2];
			var contentSize1:int = size1 - margin[_marginField1] - margin[_marginField2];
			var contentSize2:int = size2 - margin[_marginField3] - margin[_marginField4];
			
			var fillSize:int = 0;
			if(fillCount > 0)
				fillSize = contentSize1 - gapSize - unfillSize;
			
			if(fillSize == 0 && (_alignment.value & (Alignment[_alignmentKey1] as Alignment).value) > 0)
				start += (contentSize1 - unfillSize - gapSize) * 0.5;
			
			enumerator.reset();
			while(enumerator.next())
			{
				element = enumerator.current;
				if((element.fill.value & (Fill[_directionField2] as Fill).value) > 0)
				{
					element.display[_sizeField2] = contentSize2;
					element.display[_pointField2] = margin[_marginField3];
				}
				else
				{
					if((_alignment.value & (Alignment[_alignmentKey3] as Alignment).value) > 0) element.display[_pointField2] = margin[_marginField3];
					else if((_alignment.value & (Alignment[_alignmentKey4] as Alignment).value) > 0) element.display[_pointField2] = size2 - margin[_marginField4] - element.display[_sizeField2];
					else element.display[_pointField2] = margin[_marginField3] + (contentSize2 - element.display[_sizeField2]) * 0.5;
				}
				
				var isFill:Boolean = (element.fill.value & (Fill[_directionField1] as Fill).value) > 0;
				if(isFill) element.display[_sizeField1] = fillSize / fillCount;
				
				if((_alignment.value & (Alignment[_alignmentKey2] as Alignment).value) > 0)
				{
					element.display[_pointField1] = end - element.display[_sizeField1];
					end -= element.display[_sizeField1] + _gap;
				}
				else
				{
					element.display[_pointField1] = start;
					start += element.display[_sizeField1] + _gap;
//					trace(target + " : " + element.display + " : start : " + start);
				}
				
				element.display.x += element.offset.x;
				element.display.y += element.offset.y;
			}
			
			enumerator.dispose();
		}
	}
}